package com.xuecheng.media.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.media.model.dto.MediaDTO;
import com.xuecheng.api.media.model.qo.QueryMediaModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.ResourceTypeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunVODUtil;
import com.xuecheng.media.controller.MediaAuditController;
import com.xuecheng.media.convert.MediaConvert;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.mapper.MediaMapper;
import com.xuecheng.media.service.MediaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 媒资信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class MediaServiceImpl extends ServiceImpl<MediaMapper, Media> implements MediaService {

//    @Autowired
//    private ContentApiAgent contentApiAgent;


    @Value("${aliyun.region}")
    private  String region;
    @Value("${aliyun.accessKeyId}")
    private  String accessKeyId;
    @Value("${aliyun.accessKeySecret}")
    private  String accessKeySecret;
    /*
    * 业务分析：
    *   0.是否开启事务：因为是查询所以不需要
    *   1.判断关键数据
    *       前端传来的：pageNo，pageSize
    *   2.构建分页对象
    *   3.构建查询对象QueryWrappper
    *   4.调用api获得结果
    *   5.将获得的结果封装并返回
    *
    * */
    public PageVO<MediaDTO> queryMediaList(PageRequestParams params, QueryMediaModel model, Long companyId) {
        //1.判断关键数据
        //    前端传来的：pageNo，pageSize
        if(params.getPageNo()<1){
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);  //如果页码小于0，默认为1
        }

        if(params.getPageSize() <1){
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE); //默认 20
        }



        //2.构建分页对象
        Page<Media> page = new Page<>(params.getPageNo(), params.getPageSize());

        //3.构建查询对象QueryWrappper
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();

        //判断文件名是否存在，存在就用模糊查询
        if(StringUtil.isNotBlank(model.getFilename())){
            queryWrapper.like(Media::getFilename,model.getFilename());
        }

        //判断媒资审核状态
        if(StringUtil.isNotBlank(model.getAuditStatus())){
            queryWrapper.eq(Media::getAuditStatus,model.getAuditStatus());
        }

        //判断是运营平台还是教学机构
        if(!(ObjectUtils.nullSafeEquals(companyId, MediaAuditController.OPERATION_FLAG))){
            queryWrapper.eq(Media::getCompanyId,companyId);
        }

        //按照时间倒序
        queryWrapper.orderByDesc(Media::getCreateDate);



        //4.调用api获得结果
        Page<Media> pageResult = this.page(page, queryWrapper);

        List<Media> records = pageResult.getRecords();

        long total = pageResult.getTotal();

        List<MediaDTO> dtos = Collections.EMPTY_LIST;

        //将po数据集合转换为dto集合数据
        if(!(CollectionUtils.isEmpty(records))){
            //dtos = new ArrayList<>();
            dtos= MediaConvert.INSTANCE.entitys2dtos(records);
        }


        //5.将获得的结果封装并返回
        PageVO pageVO = new PageVO<>(dtos, total, params.getPageNo(), params.getPageSize());


        return pageVO;
    }



    /*
    * 业务分析：
    *   0.是否开启事务：开启
    *   1.判断关键数据
    *   2.判断媒资信息
    *       判断是否存在
    *       判断是否为审核状态
    *       判断运营的审核状态是否合法
    *   3.修改媒资信息的审核状态
    *
    *
    * */
    @Transactional
    public void approveMedia(MediaDTO dto) {

        // 1.判断关键数据
        if (StringUtil.isBlank(dto.getAuditMind())||
                StringUtil.isBlank(dto.getAuditStatus())||
                ObjectUtils.isEmpty(dto.getId())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        // 2.判断媒资信息
        //     判断是否存在
        //     判断是否是未审核状态
        Media media = this.getById(dto.getId());

        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        String auditStatus = media.getAuditStatus();
        if (!(AuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(auditStatus))) {
            ExceptionCast.cast(MediaErrorCode.E_140017);
        }

        // 判断运营的审核状态是否合法
        String auditStatusOpera = dto.getAuditStatus();
        if (AuditEnum.AUDIT_UNPAST_STATUS.equals(auditStatusOpera)) {
            ExceptionCast.cast(MediaErrorCode.E_140019);
        }

        // 3.修改媒资信息的审核状态
        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Media::getAuditStatus, dto.getAuditStatus());
        updateWrapper.set(Media::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(Media::getId, media.getId());

        boolean result = this.update(updateWrapper);
        if (!result) {
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }

    }

    /*
    * 业务分析：
    *   0.是否开启事务
    *   1.判断关键数据
    *   2.判断业务数据
    *       判断媒资是否存在
    *       判断是否是同一家机构
    *       判断媒资是否有关联关系
    *   3.删除阿里云视频
    *   4.将本地media信息删除
    *
    *
    * */
    @Transactional
    public void removeMedia(Long mediaId, Long companyId) {

        //1.判断关键数据
        if(ObjectUtils.isEmpty(mediaId) || ObjectUtils.isEmpty(companyId)){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //2.判断业务数据
        //    判断媒资是否存在
        //    判断是否是同一家机构

        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getCompanyId,companyId);
        queryWrapper.eq(Media::getId,mediaId);

        Media media = this.getOne(queryWrapper);

        if(ObjectUtils.isEmpty(media)){
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

//        //    判断媒资是否有关联关系
//        RestResponse<List<TeachplanMediaDTO>> restResponse = contentApiAgent.getByMediaId4s(mediaId);
//
//        if(!(restResponse.isSuccessful())){
//            ExceptionCast.castWithCodeAndDesc(restResponse.getCode(),restResponse.getMsg());
//        }
//
//        List<TeachplanMediaDTO> result = restResponse.getResult();
//
//        if(!(CollectionUtils.isEmpty(result))){
//            ExceptionCast.cast(MediaErrorCode.E_140003);
//        }


        //3.删除阿里云视频
        try {
            DefaultAcsClient client = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);

            String fileId = media.getFileId();

            //删除视频
            AliyunVODUtil.deleteVideo(client,fileId);

        }catch (Exception e){

            ExceptionCast.cast(MediaErrorCode.E_140016);
        }

        //4.将本地media信息删除

        boolean removeResult = this.removeById(mediaId);

        if(!removeResult){
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }
    }

    /*
    * 业务分析：
    *   0.是否开启事务：保存数据，所以开启
    *   1.判断关键数据
    *   2.获得媒资信息云服务的数据
    *       资源地址：url
    *           视频：播放地址
    *           文档：文件地址
    *   3.保存信息并判断
    *   4.将数据库最新数据返回
    * */
    @Transactional
    public MediaDTO createMedia(MediaDTO dto) {

        //1.判断关键数据
        //companyID,fileNAme,fileID
        if(ObjectUtils.isEmpty(dto.getCompanyId()) || StringUtils.isEmpty(dto.getFileId()) || StringUtils.isEmpty(dto.getFilename())){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //2.获得媒资信息云服务的数据
        //    资源地址：url
        //        视频：播放地址
        //        文档：文件地址
        String type = dto.getType();
        if(ResourceTypeEnum.VIDEO.getCode().equals(type)){
            String playUrl=getAliyunVodPlayUrl(dto.getFileId());
        }

        //3.保存信息并判断
        Media media = MediaConvert.INSTANCE.dto2entity(dto);
        //默认赋值审核属性
        media.setAuditStatus(AuditEnum.AUDIT_UNPAST_STATUS.getCode());

        boolean result = this.save(media);

        if(!result){
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }

        //4.将数据库最新数据返回
        Media po = this.getById(media.getId());

        MediaDTO resultDTO = MediaConvert.INSTANCE.entity2dto(po);

        return resultDTO;

    }


    /*
    * 业务分析：
    *   1.判断关键是数据
    *   2.判断业务数据
    *       判断媒资是否存在
    *   3.获得媒资文件的资源路径地址
    *       判断媒资类型是否是视频类型，如果是需要获得aliyun视频的地址
    *
    * */
    public String getPlayUrlByMediaId(Long mediaId, Long companyId) {

        //1.判断关键是数据
        if(ObjectUtils.isEmpty(mediaId) || ObjectUtils.isEmpty(companyId)){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //2.判断业务数据
        //    判断媒资是否存在
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getId,mediaId);

        if(!(ObjectUtils.nullSafeEquals(companyId,MediaAuditController.OPERATION_FLAG))){
            queryWrapper.eq(Media::getCompanyId,companyId);
        }

        Media media=this.getOne(queryWrapper);

        if(ObjectUtils.isEmpty(media)){
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }
        //3.获得媒资文件的资源路径地址
        //    判断媒资类型是否是视频类型，如果是需要获得aliyun视频的地址
        String type = media.getType();

        String resourceUrl=null;

        if(ResourceTypeEnum.VIDEO.getCode().equals(type)){
            resourceUrl = getAliyunVodPlayUrl(media.getFileId());
        }else if (ResourceTypeEnum.DOCUMENT.getCode().equals(type)){
            //获得的媒资文档的资源访问地址路径
        }else if (ResourceTypeEnum.WORK.getCode().equals(type)){
            //获得的媒资文档的资源访问地址路径
        }

        return resourceUrl;

    }

    /*
    * 业务分析：
    *   0.是否开启事务：查询，不开
    *   1.判断关键数据
    *       mediaId
    *   2.判断业务数据
    *       媒资是否存在
    *   3.将结果内容返回-使用Restresponse来封装
    *       不管是有还是没有都要返回结果
    *
    * */
    public RestResponse<MediaDTO> getMediaById4s(Long mediaId) {

        //1.判断关键数据
        //    mediaId
        if(ObjectUtils.isEmpty(mediaId)){
            return RestResponse.validfail(CommonErrorCode.E_100101);
        }


        //2.判断业务数据
        //    媒资是否存在
        Media media = this.getById(mediaId);

        if(ObjectUtils.isEmpty(media)){
            return RestResponse.validfail(MediaErrorCode.E_140005);
        }


        //3.将结果内容返回-使用Restresponse来封装
        //    不管是有还是没有都要返回结果
        MediaDTO mediaDTO = MediaConvert.INSTANCE.entity2dto(media);
        RestResponse<MediaDTO> response = RestResponse.success(mediaDTO);

        return response;
    }


    /**
     * 获得阿里云视频播放地址
     * @param fileId
     * @return
     */
    private String getAliyunVodPlayUrl(String fileId) {

        String playURL=null;

        try {
            DefaultAcsClient client = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);
            GetPlayInfoResponse playInfo = AliyunVODUtil.getPlayInfo(client, fileId);

            List<GetPlayInfoResponse.PlayInfo> playInfoList = playInfo.getPlayInfoList();

            if(CollectionUtils.isEmpty(playInfoList)){
                ExceptionCast.cast(MediaErrorCode.E_140018);
            }
            //获得默认第一个播放地址
            playURL = playInfoList.get(0).getPlayURL();
        } catch (Exception e) {
            log.error(MediaErrorCode.E_140012.getDesc() + " : {}",e.getMessage() );
            ExceptionCast.cast(MediaErrorCode.E_140012);
        }

        return playURL;
    }
}
